import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Scanner;

import javax.print.attribute.standard.Finishings;
import javax.swing.JFileChooser;

import org.jf.smali.smaliParser.array_literal_return;



public class parsing {

	static String path ;
	static String methodCall;
	static String classinfo;
	static String getNameOfClass;
	static String methodName;
	static String firstMethodName;
	static ArrayList<String> array = new ArrayList<String>();

	/** get the file name and pass it to the parser
	 *  
	 *  This method needs to return the file name to the parser method
	 * @throws IOException 
	 */

	public static void chooseFile() throws IOException{
		JFileChooser chooser = new JFileChooser();
		// Note: source for ExampleFileFilter can be found in FileChooserDemo,
		// under the demo/jfc directory in the Java 2 SDK, Standard Edition.



		int returnVal = chooser.showOpenDialog(chooser);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			System.out.println("You chose to open this file: " + 
					chooser.getSelectedFile().getName());     // get the file name that you need to parse.
		}
		String name = chooser.getSelectedFile().getName();
		System.out.println(name);
		Scanner sc = new Scanner(name).useDelimiter("\\s*.smali\\s*");
		firstMethodName= sc.nextLine();
		System.out.println(firstMethodName);
		parser(name);

		//addMethod(name);	
	}



	/**
	 * 
	 * @param filename
	 * @throws IOException
	 */

	public static void parser(String filename) throws IOException{



		LineNumberReader lnr =  new LineNumberReader(new FileReader(filename));;
		int i = 0;
		//BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("textnew.txt"));
		Scanner scan = new Scanner(new FileReader(filename));

		String token = scan.nextLine();

		Scanner sc = new Scanner(filename).useDelimiter("\\s*.smali\\s*");

		getNameOfClass = sc.next();

		System.out.println(getNameOfClass);

		getClassDetail(filename);


		Scanner scan1;

		int start = token.indexOf("L");
		int end = token.indexOf(getNameOfClass);

		System.out.println(start + " ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo " + end);
		path = token.substring(start , end );
		System.out.println("PATH = " + path);



		while (scan.hasNext()) {

			lnr.setLineNumber(++i);



			scan1 = new Scanner(token);
			//System.out.println("scan token = " + scan1.hasNext("invoke-virtual"));
			if (scan1.hasNext(".method")){
				// methods called
				System.out.println(token.contains("invoke-virtual"));


				methodCall = token;
				System.out.println("yes + " + methodCall);
				//System.out.println(scan.nextLine() + " " + lnr.getLineNumber());
			}


			array.add(token);

			token = scan.nextLine();
			//System.out.println("token = "+token);
		}

		// call the method to add the line.
		// addCallMethod(methodCall , filename);
		// System.out.println(token);
		array.add(token);


	}

	//	public static void testArray(){
	//		
	//		for (int i = 0; i <array.size(); i++){
	//			
	//			System.out.println(array.get(i));
	//		}
	//	}
	/**
	 * 
	 * @param filename
	 * @return
	 * @throws FileNotFoundException
	 */




	public static String getClassDetail(String filename) throws FileNotFoundException {



		Scanner scan = new Scanner(new File(filename)).useDelimiter("\\s*.source\\s*");
		classinfo = scan.nextLine();	
		System.out.println("clssInfo"+classinfo);
		return classinfo;
	}


	/** read the HelloAndroidActivity and add the hacks
	 * 
	 * @param methodName
	 * @param filename 
	 */
	public static void addCallMethod(String filename){
		// 
		// 

		Scanner d = new Scanner(System.in);
		methodName = d.next();// change it later on too be a parameter.
		System.out.println("methodName :" + methodName);

		BufferedWriter bufferedWriter = null;
		FileReader fr;

		try {
			fr = new FileReader(new File(filename));
			bufferedWriter = new BufferedWriter(new FileWriter("addedCallMethod.Smali"));

			//	        BufferedReader br = new BufferedReader(fr);
			//	        String line1 = br.readLine();
			Scanner scan = new Scanner(fr);

			String token1 = scan.nextLine();
			System.out.println(token1);


			while (scan.hasNext()) {

				processLine(token1);



				System.out.println("entered loop");
				//System.out.println("line= "+ line);
				//System.out.println("line1= "+ token1);
				if (processLine(token1)){

					System.out.println("booo");
					//bufferedWriter.write(token1);
					bufferedWriter.write(token1);
					bufferedWriter.newLine();
					token1 = scan.nextLine();
					bufferedWriter.write(token1);
					bufferedWriter.newLine();
					bufferedWriter.write("invoke-static {}, "+path+InstCode.fileName+";->"+"before"+"()V");
					System.out.println("invoke-static {},, "+path+";->"+"methodName"+"()V");

					//	invoke-virtual {p0}, LHelloAndroid/workspace/HelloAndroidActivity;->print()V


					bufferedWriter.newLine();
				}

				else{

					bufferedWriter.write(token1);
					bufferedWriter.newLine();
				}

				//line1 = br.readLine();
				token1 = scan.nextLine();
			}
			bufferedWriter.write(token1); // write the end method

			//br.close();
			scan.close();

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
			//Close the BufferedWriter
			try {

				if (bufferedWriter != null) {
					bufferedWriter.flush();
					bufferedWriter.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 *  keep looping and adding hacks till the user type done, then generate the final file.
	 * @throws IOException 
	 */

	public static void addHackToFile() throws IOException{

		Scanner d = new Scanner(System.in);
		//   methodName = d.next();// change it later on too be a parameter.
		//System.out.println("methodName :" + methodName);


		do{
			try {

				System.out.println("Please Enter the name of the method that, to add hacks!");
				// scan the machin' name
				methodName = d.next();// change it later on too be a parameter.



				for (int i = 0; i <array.size(); i++){

					String token1 = array.get(i);

					//processLine(token1);

					//System.out.println(array.get(i));

					if (processLine(token1)){

						System.out.println(token1);

						array.add(i+1, "invoke-static {}, "+path+InstCode.fileName+";->"+"before"+"()V");


						//////////////
						for (int j = i; j < array.size(); j++){

							String token2 = array.get(j);


							if(token2.equalsIgnoreCase(".end method")){

								array.add(j-1, "invoke-static {}, "+path+InstCode.fileName+";->"+"after"+"()V");
								System.out.println("true");
								token2 = array.get(j+2);
								break;

							}
						}

					}

				}




			} catch (Exception e) {
				// TODO: handle exception
				System.out.println("PLEASE ENTER A VALID INPUT!!");


			}

		}while (!methodName.equalsIgnoreCase("exit"));

		System.out.println("EXIT!");


		testArray(); // test that it adds the value correctly

	}
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public static void testArray() throws IOException{
	

		
		try {
			FileWriter fstream = new FileWriter("FinalVersion");
			PrintWriter bufferedWriter = new PrintWriter(fstream);

			for (int i = 0; i <array.size(); i++){
				String line = array.get(i).toString();
			
				
				
				try {
					bufferedWriter.println(line.substring(1,line.length()-1));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					System.out.println("PROBLEM WRITING INTO A FILE!");
					System.out.println("yes");
				}
				System.out.println(array.get(i));
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * method for processing lines in different ways.
	 * @param line
	 * @return 
	 */
	public static boolean processLine(String line) {
		Scanner sc = new Scanner(line);
		//System.out.println("line" + line);

		while (sc.hasNext()){
			String theMethod = sc.next();

			if (methodName.equals(theMethod)){
				System.out.println("theMethod:  "+  theMethod);
				return true;
			}
		}
		return false;
	}
	/** not IN USE!!
	 * 
	 * @param line
	 * @param filename
	 */
	public static void addMethod(String filename){

		BufferedWriter bufferedWriter = null;
		FileReader fr;

		try {
			fr = new FileReader(new File(filename));
			bufferedWriter = new BufferedWriter(new FileWriter("final.txt"));



			//	        BufferedReader br = new BufferedReader(fr);
			//	        String line1 = br.readLine();
			Scanner scan = new Scanner(fr);



			String token1 = scan.nextLine();

			//parser(filename); // add a call method to Print()
			while (scan.hasNext()) {

				//System.out.println("line= "+ line);
				//System.out.println("line1= "+ token1);
				if (token1.equals(".end method")){

					System.out.println("booo");
					bufferedWriter.write(token1);
					bufferedWriter.newLine();
					bufferedWriter.newLine();
					bufferedWriter.write(
							".method public print()V" + "\n" +
									".registers 4" + "\n" +
									".prologue" + "\n" +
									".line 23" + "\n" +
									"invoke-virtual {p0}, LHelloAndroid/workspace/HelloAndroidActivity;->getApplicationContext()Landroid/content/Context;" + "\n" +
									"move-result-object v0" + "\n" +
									"const-string v1," + " \"show test\"" + "\n" +
									"const/4 v2, 0x1" + "\n" +
									"invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;" + "\n" +
									".line 26" + "\n" +
									"return-void" + "\n" +
							".end method"); 


					bufferedWriter.newLine();
				}

				else{

					bufferedWriter.write(token1);
					bufferedWriter.newLine();
				}

				//line1 = br.readLine();
				token1 = scan.nextLine();
			}
			bufferedWriter.write(token1); // write the end method

			//br.close();
			scan.close();

		} catch (Exception e) {
			e.printStackTrace();

		} finally {
			//Close the BufferedWriter
			try {

				if (bufferedWriter != null) {
					bufferedWriter.flush();
					bufferedWriter.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}



	}
	// remove before submitt
	public static void chooseFile2() throws IOException{
		JFileChooser chooser = new JFileChooser();
		// Note: source for ExampleFileFilter can be found in FileChooserDemo,
		// under the demo/jfc directory in the Java 2 SDK, Standard Edition.



		int returnVal = chooser.showOpenDialog(chooser);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			System.out.println("You chose to open this file: " + 
					chooser.getSelectedFile().getName());     // get the file name that you need to parse.
		}
		String name = chooser.getSelectedFile().getName();
		System.out.println(name);

		//addCallMethod(name);
		addHackToFile();

	}

	public static void main(String args[]) throws IOException{

		//chooseFile();
		//addMethod();
		//System.out.println("print");
	}







}
